// KS0108B.c driver

#include "KS0108.h"

//#define KS0108_MAIN_TEST 1

void KS0108Delayns(uint32_t ns) {
//    while (ns--);
}

uint8_t KS0108Open(struct sKS0108 *this) {
    PinOpen(&this->en, PIN_OUTPUT, PIN_LOW);
    PinOpen(&this->rw, PIN_OUTPUT, PIN_LOW);
    PinOpen(&this->rs, PIN_OUTPUT, PIN_LOW);
    PinOpen(&this->cs, PIN_OUTPUT, PIN_HIGH);
    BusOpen(&this->db, BUS_OUTPUT, BUS_LOW);

    KS0108Write(this, KS0108_POWER_ON);
    KS0108Write(this, KS0108_Y | (KS0108_Y_MASK & 0));
    KS0108Write(this, KS0108_X | (KS0108_X_MASK & 0));
    KS0108Write(this, KS0108_LINE | (KS0108_LINE_MASK & 0));
    return 0;
}

uint8_t KS0108Close(struct sKS0108 *this) {
    KS0108Write(this, KS0108_POWER_OFF);
    BusClose(&this->db);
    PinClose(&this->cs);
    PinClose(&this->en);
    PinClose(&this->rw);
    PinClose(&this->rs);
    return 0;
}

uint8_t KS0108Read(struct sKS0108 *this) {
    uint8_t db;

    PinWrite(&this->rw, PIN_HIGH);
    PinWrite(&this->rs, PIN_LOW);
    BusDir(&this->db, BUS_INPUT);

    PinWrite(&this->cs, PIN_LOW);
    KS0108Delayns(4);
    PinWrite(&this->en, PIN_HIGH);
    KS0108Delayns(4);
    db = BusRead(&this->db);
    PinWrite(&this->en, PIN_LOW);
    PinWrite(&this->cs, PIN_HIGH);

    BusDir(&this->db, BUS_OUTPUT);

    return db;
}

uint8_t KS0108ReadData(struct sKS0108 *this) {
    uint8_t db;

    PinWrite(&this->rw, PIN_HIGH);
    PinWrite(&this->rs, PIN_HIGH);
    BusDir(&this->db, BUS_INPUT);

    PinWrite(&this->cs, PIN_LOW);
    KS0108Delayns(4);
    //	Dummy read. Not works on Proteus ISIS
    PinWrite(&this->en, PIN_HIGH);
    KS0108Delayns(4);
    PinWrite(&this->en, PIN_LOW);
    KS0108Delayns(4);
    //
    PinWrite(&this->en, PIN_HIGH);
    KS0108Delayns(4);
    db = BusRead(&this->db);
    PinWrite(&this->en, PIN_LOW);
    PinWrite(&this->cs, PIN_HIGH);

    BusDir(&this->db, BUS_OUTPUT);

    return db;
}

void KS0108Write(struct sKS0108 *this, uint8_t data) {
    PinWrite(&this->rw, PIN_LOW);
    PinWrite(&this->rs, PIN_LOW);
    BusDir(&this->db, BUS_OUTPUT);

    PinWrite(&this->cs, PIN_LOW);
    KS0108Delayns(4);
    PinWrite(&this->en, PIN_HIGH);
    KS0108Delayns(4);
    BusWrite(&this->db, data);
    PinWrite(&this->en, PIN_LOW);
    PinWrite(&this->cs, PIN_HIGH);

//    while (KS0108Read(this) & KS0108_BUSY) {
  //      KS0108Delayns(10);
    //}
    return;
}

void KS0108WriteData(struct sKS0108 *this, uint8_t data) {
    PinWrite(&this->rw, PIN_LOW);
    PinWrite(&this->rs, PIN_HIGH);
    BusDir(&this->db, BUS_OUTPUT);

    PinWrite(&this->cs, PIN_LOW);
    KS0108Delayns(4);
    PinWrite(&this->en, PIN_HIGH);
    KS0108Delayns(4);
    BusWrite(&this->db, data);
    PinWrite(&this->en, PIN_LOW);
    PinWrite(&this->cs, PIN_HIGH);

 //   while (KS0108Read(this) & KS0108_BUSY) {
   //     KS0108Delayns(10);
   // }
    return;
}


#ifdef KS0108_MAIN_TEST
#include	"P24FJ64GA004.h"


struct sKS0108 myKS0108 = {
    { 7, &PORTA, &TRISA, &LATA},
    { 0, &PORTA, &TRISA, &LATA},
    { 2, &PORTA, &TRISA, &LATA},
    { 1, &PORTA, &TRISA, &LATA},
    { 0, &PORTC, &TRISC, &LATC}
};

int main(void) {
    int x, y;

    if (0 != KS0108Open(&myKS0108)) {
        return -1; // Can't open KS0108
    }

    for (y = 0; y < KS0108_Y_MASK + 1; y++) {
        for (x = 0; x < KS0108_X_MASK + 1; x++) {
            KS0108Write(&myKS0108, KS0108_X | (KS0108_X_MASK & x));
            KS0108Write(&myKS0108, KS0108_Y | (KS0108_Y_MASK & y));
            KS0108WriteData(&myKS0108, 0xFF);
        }
    }

    KS0108Close(&myKS0108);

    return 0;
}

#endif //KS0108_MAIN_TEST
